package com.simple.create.singleton.sample2;

import com.simple.LogUtil;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * 单例模式2
 * 使用synchronized关键字锁住com.simple.create.singleton.sample2.Singleton#getInstance()
 * 避免了多线程调用的时候生成多个实例的问题
 * 弊端:
 * synchronized关键字加在方法上时, 通过实例调用这些加了关键字的方法时, 需要每次都要拿到对象的锁;
 * synchronized关键字加在静态方法上时, 通过类名调用这些加了关键字的静态方法时, 需要每次都拿到类的锁;
 * 每次调用都要对对象加锁, 但其实只需在第一次创建对象的时候需要加锁, 之后就不需要了, 直接取就行, 所以会造成性能问题
 *
 * @author simple
 * @version 1.0
 * @date 2018/12/6 14:39
 * @since 1.0
 */
public class Singleton {
    private static AtomicInteger count = new AtomicInteger(0);

    /**
     * 持有私有的静态实例, 防止被引用, 赋值为null, 实现延迟加载
     */
    private static Singleton instance = null;

    /**
     * 私有的构造方法, 防止被外部实例化(反射?)
     */
    private Singleton() {

    }

    public static int getInstanceCount() {
        return count.get();
    }

    /**
     * 提供静态方法, 用于创建实例
     *
     * @return 实例
     */
    public static synchronized Singleton getInstance() {
        if (null == instance) {
            LogUtil.info("第" + count.incrementAndGet() + "个实例开始创建...");
            instance = new Singleton();
        }
        return instance;
    }

    /**
     * 如果该对象被序列化, 可以保证对象在序列化前后保持一致
     *
     * @return 实例
     */
    public Object readResolve() {
        return instance;
    }
}
